The not-so-final word on final #JVMLS

Developers have often heard the advice to “prefer immutability”. Immutability confers many advantages, since an immutable object can be only in one state and therefore can be shared freely with untrusted code and across multiple threads. Java’s main tool for managing immutability is final fields. Unfortunately, using final fields comes with limitations which restrict their use in many real-world applications.

While the compiler, and the putfield bytecode protect against errant writes to final fields, there are some gaps. For instance, final fields can be reassigned more than once, either inside the constructor, or even outside (e.g. using setAccessible). Because of this, final fields can’t be trusted not to change (or to change only once), which undermines the integrity of Java applications, and precludes some important performance optimizations (such as constant-folding).

Moreover, initializaton of final fields is rather inflexible: they must be set eagerly, either during construction (for instance fields) or during class initialization (for static fields) – and in the exact order in which they have been declared. Because of this, initializaton of final fields cannot be shifted in time, so as to reduce the overall burden on application startup.

In this talk we will look at some of the steps we’re taking to address these limitations, and enable Java to take better advantage of immutable data.

Make sure to check the JVMLS 2025 playlist.